package service

import (
	"context"
	"fmt"
	"os"
	"path/filepath"
	"regexp"
	"sort"
	"strconv"
	"strings"
	"time"

	"go-file-perception-model/internal/model"
	"go-file-perception-model/internal/repository"
	"go-file-perception-model/pkg/vector"
)

// SemanticSearchService 语义搜索服务
type SemanticSearchService struct {
	vectorDB       vector.VectorDB
	embeddingModel EmbeddingModel
	fileMonitorRepo repository.FileMonitorRepository
}

// NewSemanticSearchService 创建语义搜索服务实例
func NewSemanticSearchService(vectorDB vector.VectorDB, embeddingModel EmbeddingModel, fileMonitorRepo repository.FileMonitorRepository) *SemanticSearchService {
	return &SemanticSearchService{
		vectorDB:       vectorDB,
		embeddingModel: embeddingModel,
		fileMonitorRepo: fileMonitorRepo,
	}
}

// Search 执行语义搜索
func (s *SemanticSearchService) Search(req model.SemanticSearchRequest) ([]*model.SearchResult, error) {
	// 记录搜索开始时间用于性能监控
	startTime := time.Now()
	fmt.Printf("[SemanticSearch] Starting search for query: %s\n", req.Query)
	
	// 获取查询的嵌入向量
	queryVector, err := s.embeddingModel.Embedding(context.Background(), req.Query)
	if err != nil {
		fmt.Printf("[SemanticSearch] Error getting query embedding: %v\n", err)
		return nil, fmt.Errorf("failed to get query embedding: %w", err)
	}
	fmt.Printf("[SemanticSearch] Successfully generated query embedding with dimensions: %d\n", len(queryVector))

	// 构建过滤器
	var filter *vector.Filter
	if len(req.FileTypes) > 0 || len(req.Directories) > 0 {
		filter = &vector.Filter{}

		// 添加文件类型过滤条件
		if len(req.FileTypes) > 0 {
			should := make([]vector.Condition, 0, len(req.FileTypes))
			for _, fileType := range req.FileTypes {
				should = append(should, vector.Condition{
					Key:   "file_type",
					Match: &vector.MatchValue{Value: fileType},
				})
			}
			filter.Should = should
		}

		// 添加目录过滤条件
		if len(req.Directories) > 0 {
			must := make([]vector.Condition, 0, len(req.Directories))
			for _, dir := range req.Directories {
				// 确保目录路径以斜杠结尾，以便正确匹配子目录中的文件
				dirPath := dir
				if !strings.HasSuffix(dirPath, "/") && !strings.HasSuffix(dirPath, "\\") {
					dirPath += string(filepath.Separator)
				}
				must = append(must, vector.Condition{
					Key:   "file_path",
					Match: &vector.MatchValue{Value: dirPath},
				})
			}
			filter.Must = must
		}
	}

	// 确定搜索限制
	searchLimit := req.Limit
	if req.EnableDedup {
		// 如果启用去重归纳，扩大搜索限制
		if req.DedupMultiplier <= 0 {
			req.DedupMultiplier = 100 // 默认倍数
		}
		searchLimit = req.Limit * req.DedupMultiplier
		// 限制最大搜索数量，避免性能问题
		if searchLimit > 1000 {
			searchLimit = 1000
		}
	}

	// 执行向量搜索
	fmt.Printf("[SemanticSearch] Executing vector search with limit: %d, threshold: %.2f\n", searchLimit, req.Threshold)
	results, err := s.vectorDB.SearchPoints(context.Background(), queryVector, searchLimit, req.Threshold, filter)
	if err != nil {
		fmt.Printf("[SemanticSearch] Vector search failed: %v\n", err)
		return nil, fmt.Errorf("failed to search points: %w", err)
	}
	fmt.Printf("[SemanticSearch] Vector search completed, found %d raw results\n", len(results))

	// 填充搜索结果
	fmt.Printf("[SemanticSearch] Processing %d search results\n", len(results))
	for i, result := range results {
		// 设置文件类型
		result.FileType = s.getFileType(result.FilePath)
		result.IndexedAt = time.Now()
		
		// 从SQLite数据库获取文件大小信息
		// 首先尝试从文件路径中提取目录ID
		dirPath := filepath.Dir(result.FilePath)
		directoryRecord, err := s.fileMonitorRepo.GetDirectoryRecordByPath(dirPath)
		if err == nil && directoryRecord != nil {
			fileRecord, err := s.fileMonitorRepo.GetFileRecordByPath(directoryRecord.ID, result.FilePath)
			if err == nil && fileRecord != nil {
				result.FileSize = fileRecord.FileSize
			} else {
				// 如果从数据库获取失败，尝试从文件系统获取
				if fileInfo, err := os.Stat(result.FilePath); err == nil {
					result.FileSize = fileInfo.Size()
				} else {
					fmt.Printf("[SemanticSearch] Warning: Could not get file size for %s: %v\n", result.FilePath, err)
				}
			}
		} else {
			// 如果无法获取目录记录，直接从文件系统获取
			if fileInfo, err := os.Stat(result.FilePath); err == nil {
				result.FileSize = fileInfo.Size()
			} else {
				fmt.Printf("[SemanticSearch] Warning: Could not get directory record or file size for %s: %v\n", result.FilePath, err)
			}
		}
		
		// 记录处理进度
		if (i+1)%10 == 0 || i == len(results)-1 {
			fmt.Printf("[SemanticSearch] Processed %d/%d results\n", i+1, len(results))
		}
		
		// MCP工具不需要highlight信息，跳过高亮内容生成
		result.Highlight = ""
	}

	// 如果启用去重归纳，对结果进行去重处理
	if req.EnableDedup {
		fmt.Printf("[SemanticSearch] Applying deduplication with limit: %d\n", req.Limit)
		results = s.deduplicateResults(results, req.Limit)
		fmt.Printf("[SemanticSearch] Deduplication completed, %d unique results\n", len(results))
	} else {
		// 如果不启用去重，只返回指定数量的结果
		originalCount := len(results)
		if originalCount > req.Limit {
			results = results[:req.Limit]
		}
		fmt.Printf("[SemanticSearch] Returning %d of %d results (deduplication disabled)\n", len(results), originalCount)
	}
	
	// 记录搜索完成时间和性能指标
	duration := time.Since(startTime)
	fmt.Printf("[SemanticSearch] Search completed in %v, returning %d final results\n", duration, len(results))

	return results, nil
}

// deduplicateResults 对搜索结果进行去重归纳
func (s *SemanticSearchService) deduplicateResults(results []*model.SearchResult, limit int) []*model.SearchResult {
	if len(results) == 0 {
		return results
	}

	// 按文件路径分组
	fileGroups := make(map[string][]*model.SearchResult)
	for _, result := range results {
		fileGroups[result.FilePath] = append(fileGroups[result.FilePath], result)
	}

	// 对每个文件组，选择得分最高的结果作为代表
	var dedupResults []*model.SearchResult
	for _, group := range fileGroups {
		// 找到得分最高的结果
		var bestResult *model.SearchResult
		var bestScore float32
		for _, result := range group {
			if result.Score > bestScore {
				bestScore = result.Score
				bestResult = result
			}
		}

		if bestResult != nil {
			// 在结果中添加匹配次数信息
			bestResult.Content = fmt.Sprintf("[匹配次数: %d] %s", len(group), bestResult.Content)
			dedupResults = append(dedupResults, bestResult)
		}
	}

	// 按得分和匹配次数排序
	sort.Slice(dedupResults, func(i, j int) bool {
		// 首先按得分排序
		if dedupResults[i].Score != dedupResults[j].Score {
			return dedupResults[i].Score > dedupResults[j].Score
		}
		// 得分相同的情况下，按匹配次数排序
		countI := s.extractMatchCount(dedupResults[i].Content)
		countJ := s.extractMatchCount(dedupResults[j].Content)
		return countI > countJ
	})

	// 限制返回数量
	if len(dedupResults) > limit {
		dedupResults = dedupResults[:limit]
	}

	return dedupResults
}

// extractMatchCount 从内容中提取匹配次数
func (s *SemanticSearchService) extractMatchCount(content string) int {
	// 使用正则表达式提取匹配次数
	re := regexp.MustCompile(`^\[匹配次数: (\d+)\]`)
	matches := re.FindStringSubmatch(content)
	if len(matches) > 1 {
		if count, err := strconv.Atoi(matches[1]); err == nil {
			return count
		}
	}
	return 1
}

// getFileType 根据文件路径获取文件类型
func (s *SemanticSearchService) getFileType(filePath string) string {
	if filePath == "unknown" {
		return "unknown"
	}
	ext := strings.ToLower(filepath.Ext(filePath))
	switch ext {
	case ".txt":
		return "text"
	case ".md":
		return "markdown"
	case ".go":
		return "go"
	case ".py":
		return "python"
	case ".js":
		return "javascript"
	case ".ts":
		return "typescript"
	case ".java":
		return "java"
	case ".c":
		return "c"
	case ".cpp", ".cxx", ".cc", ".h", ".hpp":
		return "c++"
	default:
		return "unknown"
	}
}